#ifndef ALTTILESET_H
#define ALTTILESET_H

#include <QImage>
#include <QSharedData>
#include <QSharedDataPointer>

namespace Alt {
     /*! Helper class for Alt::Tileset. Provides copy-on-write properties for Alt::Tileset. */
     class TilesetData : public QSharedData {
     public:
          /*! Default constructor.
               \param image The tile graphic.
               \param tileSize The size of each tile.
               \param padding horizontal and vertical padding between frames. */
          TilesetData(const QImage& image = QImage(), const QSize& tileSize = QSize(1,1), const QPoint& padding = QPoint(0,0));

          /*! Copy constructor.
               \param other The tileset data to copy. */
          TilesetData(const TilesetData& other);

          /*! The graphic from which tiles are generated. */
          QImage image;

          /*! The horizontal and vertical padding between each frame. */
          QPoint padding;

          /*! The size of each tile. */
          QSize tileSize;
     };

     /*! A class from which reusable tiles are generated. This class is intended for use with the Alt::TiledMap class.
          A tileset consists of a base graphic consisting of equally spaced and sized tile graphics. */
     class Tileset {
     public:
          /*! Default constructor.
               \param image The tile graphic.
               \param tileSize The size of each tile.
               \param padding horizontal and vertical padding between frames. */
          Tileset(const QImage& image = QImage(), const QSize& tileSize = QSize(1, 1), const QPoint& padding = QPoint(0,0));
          /*! Copy constructor.
               \param other The tileset to copy. */
          Tileset(const Tileset& other);

          /*! The width of the tileset, in tiles. */
          int columnCount() const;

          /*! The horizontal padding between frames. */
          int horizontalPadding() const;

          /*! The graphic from which tiles are rendered. */
          const QImage& image() const;

          /*! Whether the tileset is valid.
               An empty image or invalid tile size will result in an invalid tileset. */
          bool isValid() const;

          /*! The maximum possible tile number. Tile numbers start at 0. */
          int maxTileNumber() const;

          /*! Sum of the tile height and vertical padding. */
          int paddedTileHeight() const;

          /*! Sum of the tile size and padding. */
          QSize paddedTileSize() const;

          /*! Sum of the tile width and horizontal padding. */
          int paddedTileWidth() const;

          /*! The horizontal and vertical padding between each frame. */
          const QPoint& padding() const;

          /*! The height of the tileset, in tiles */
          int rowCount() const;

          /*! Sets the horizontal padding between tile frames.
               \param hPadding The new horizontal padding. */
          void setHorizontalPadding(int hPadding);

          /*! Sets the graphic from which tiles are rendered.
               \param image The new graphic. */
          void setImage(const QImage& image);

          /*! Sets the horizontal and vertical padding between frames.
               \param padding The new padding. */
          void setPadding(const QPoint& padding);

          /*! Sets the height of each tile graphic.
               \param height The new tile height. */
          void setTileHeight(int height);

          /*! Sets the size of each tile graphic.
               \param tileSize The new tile size. */
          void setTileSize(const QSize& tileSize);

          /*! Sets the width of each tile graphic.
               \param width The new tile width. */
          void setTileWidth(int width);

          /*! Sets the vertical padding between tile frames.
               \param vPadding The new vertical padding. */
          void setVerticalPadding(int vPadding);

          /*! Retrieves a tile graphic's rectangle.
               \param tileNumber The tile number.
                    The top-left most tile is considered tile 0, and increments going left->right, top->bottom.
                    If a number greater than maxTileNumber() is passed, the tile values will loop back to the start (tileNumber = tileNumber % maxTileNumber()).
                    If a negative number is passed, tiles will be counted started with the last tile.
               \return The rectangle containing the tile's graphic. */
          QRect tileRect(int tileNumber) const;

          /*! The size of each tile. */
          const QSize& tileSize() const;

          /*! The height of each tile frame. */
          int tileHeight() const;

          /*! The width of each tile frame. */
          int tileWidth() const;

          /*! The dimensions of the map, in terms of tiles. */
          QSize size() const;

          /*! The vertical padding between tile frames. */
          int verticalPadding() const;

     private:
          /*! Implictly shared member data. */
          QSharedDataPointer<TilesetData> m_data;
     };

     /*! Saves a tileset to a stream.
          \param stream The stream to save into.
          \param tileset The tileset to save. */
     QDataStream& operator << (QDataStream& stream, const Tileset& tileset);

     /*! Loads a tileset from a stream.
          \param stream The stream to load from.
          \param tileset The tile to load. */
     QDataStream& operator >> (QDataStream& stream, Tileset& tileset);

}

#endif
